package com.app.business.service;

import com.app.business.model.HousePersonForProperty;
import com.app.business.model.ReduceRecords;
import com.app.system.jpa.JpaBaseDao;
import com.app.system.utils.CollectionUtils;
import com.app.system.utils.dataType.BigDecimalUtils;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by szy on 2024/6/11
 */
@SuppressWarnings(value = "ALL")
@Service
@Transactional
public class ReduceRecordsService extends JpaBaseDao<ReduceRecords,Integer> {
    @Autowired
    private HousePersonForPropertyService housePersonForPropertyService;

    /**
     * 一次性计算十年物业减免费用
     * @param housePersonForProperty
     */
    public synchronized void cal(HousePersonForProperty housePersonForProperty) {
        if (housePersonForProperty.getStartDate() != null) {
            Date startDate = housePersonForProperty.getStartDate();
            // 设置开始年份和月份
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);
            int startYear = calendar.get(Calendar.YEAR);
            int startMonth = calendar.get(Calendar.MONTH) + 1;//存在偏值,所以月份要加1


            BigDecimal propertyPrice = housePersonForProperty.getHouse().getAzProject().getPropertyPrice(); //小区对应应交物业费单价
            BigDecimal jmArea = housePersonForProperty.getFreeArea();//应减免面积

            //先删除之前的旧数据
            this.deleteByHousePersonForPropertyId(housePersonForProperty.getId());
            //50 60 【五免五减半】 批量保存未来10年的费用减免情况 前五年全免、后五年物业费单价减半
            if (housePersonForProperty.getHouse().getContract() != null && housePersonForProperty.getHouse().getContract().getPropertyType() != null) {
                if (housePersonForProperty.getHouse().getContract().getPropertyType() == 1 || housePersonForProperty.getHouse().getContract().getPropertyType() == 2){
                    this.calOneSon(housePersonForProperty,startYear,startMonth,propertyPrice,jmArea);
                }
                //70 【五免五减半】 批量保存未来5年的费用减免情况
                if (housePersonForProperty.getHouse().getContract().getPropertyType() == 3){
                    this.calTwoSon(housePersonForProperty,startYear,startMonth,propertyPrice,jmArea);
                }
            }
            //删除面积为0的数据,减少数据量,方便统计
            /*this.deleteByZero(housePersonForProperty.getId());*/
        }
    }

    /**
     *  50 60【五免五减半循环保存】
     * @param housePersonForProperty 参与减免人员信息
     * @param startYear 开始年份
     * @param startMonth 开始月份
     * @param propertyPrice 物业费单价
     * @param jmArea 人员减免面积
     */
    public synchronized void calOneSon(HousePersonForProperty housePersonForProperty,int startYear,int startMonth,BigDecimal propertyPrice,BigDecimal jmArea) {
        //一次性计算未来十年的物业费减免数据
        for (int yearOffset = 0; yearOffset <= 10; yearOffset++) {
            int year = startYear + yearOffset;
            for (int month = 1; month <= 12; month++) {
                BigDecimal jmMonthMoney = calculateMonthlyAmount(year, month, startYear, startMonth,propertyPrice,jmArea);
                //将数据存储到数据库中
                //先删除所有的减免数据
                ReduceRecords reduceRecords = new ReduceRecords();
                reduceRecords.setYear(year);
                reduceRecords.setMonth(month);
                reduceRecords.setMoney(jmMonthMoney);
                reduceRecords.setHousePersonForProperty(housePersonForProperty);
                this.save(reduceRecords);
            }
        }
    }

    /**
     *  70【五免五减半循环保存】 第一年收20% 第二年收40% 第三年收60% 第四年收80%
     * @param housePersonForProperty 参与减免人员信息
     * @param startYear 开始年份
     * @param startMonth 开始月份
     * @param propertyPrice 物业费单价
     * @param jmArea 人员减免面积
     */

    public synchronized void calTwoSon(HousePersonForProperty housePersonForProperty,int startYear,int startMonth,BigDecimal propertyPrice,BigDecimal jmArea) {
        //一次性计算未来十年的物业费减免数据
        for (int yearOffset = 0; yearOffset <= 4; yearOffset++) {
            int year = startYear + yearOffset;
            for (int month = 1; month <= 12; month++) {
                BigDecimal jmMonthMoney = calculateMonthlyAmountTwo(year, month, startYear, startMonth,propertyPrice,jmArea);
                //将数据存储到数据库中
                //先删除所有的减免数据
                ReduceRecords reduceRecords = new ReduceRecords();
                reduceRecords.setYear(year);
                reduceRecords.setMonth(month);
                reduceRecords.setMoney(jmMonthMoney);
                reduceRecords.setHousePersonForProperty(housePersonForProperty);
                this.save(reduceRecords);
            }
        }
    }


    /**
     * 50 60 五免五减半方法
     * 物业费减免主计算方法
     * @param currentYear 当前年份
     * @param currentMonth 当前月份
     * @param startYear 开始年份
     * @param startMonth 开始月份
     * @param propertyPrice 小区对应物业费单价
     * @param jmArea 人员参与减免面积
     * @return
     */
    public static BigDecimal calculateMonthlyAmount(int currentYear, int currentMonth, int startYear, int startMonth,BigDecimal propertyPrice,BigDecimal jmArea) {
        // 如果当前年份小于开始年份，或者当前年份等于开始年份但当前月份小于开始月份
        if (currentYear < startYear || (currentYear == startYear && currentMonth < startMonth) || (currentYear == startYear + 10 && currentMonth >= startMonth)) {
            return BigDecimal.ZERO;//此处不计算
        }
        // 如果当前年份大于开始年份+10，或者当前年份等于开始年份+10但当前月份大于7月
        else if ((currentYear == startYear + 5 && currentMonth >= startMonth) || (currentYear > startYear + 5 && currentYear < startYear + 10) || (currentYear == startYear + 10 && currentMonth <= startMonth)) {
            return BigDecimalUtils.getBigAndBigMul(
                    BigDecimalUtils.getBigAndBigDiv(propertyPrice,new BigDecimal("2"),2),
                    jmArea
            );//返回减免面积 * 物业费单价*0.5
        }
        // 在开始年份到开始年份+10之间的年份，每月领取60元
        else {
            return BigDecimalUtils.getBigAndBigMul(propertyPrice,jmArea);//返回减免面积 * 物业费单价*1
        }
    }
    //开始减免时间若是当月1日的 则本月给予一个月减免  若减免日是15日的则给予半个月的物业费减免【否则一律按当月全部减免】


    /**
     * 70 减免办法 逐年递减
     * 物业费减免主计算方法
     * @param currentYear 当前年份
     * @param currentMonth 当前月份
     * @param startYear 开始年份
     * @param startMonth 开始月份
     * @param propertyPrice 小区对应物业费单价
     * @param jmArea 人员参与减免面积
     * @return
     */
    public static BigDecimal calculateMonthlyAmountTwo(int currentYear, int currentMonth, int startYear, int startMonth,BigDecimal propertyPrice,BigDecimal jmArea) {
        // 如果当前年份小于开始年份，或者当前年份等于开始年份但当前月份小于开始月份
        if (currentYear < startYear || (currentYear == startYear && currentMonth < startMonth) || (currentYear == startYear + 4 && currentMonth >= startMonth)) {
            return BigDecimal.ZERO;//此处不计算
        } else  {
            //物业费缴纳比例逐年递减 80% 60% 40% 20%
            BigDecimal newPrice = BigDecimal.ZERO;//定义新物业费单价
            if ((currentYear == startYear && currentMonth >= startMonth) || (currentYear == startYear + 1 && currentMonth < startMonth)) {//第一年减免
                newPrice = BigDecimalUtils.getBigAndBigMul(propertyPrice,new BigDecimal(0.8));
            } else if ((currentYear == startYear + 1 && currentMonth >= startMonth) || (currentYear == startYear + 2 && currentMonth < startMonth)){
                newPrice = BigDecimalUtils.getBigAndBigMul(propertyPrice,new BigDecimal(0.6));
            } else if ((currentYear == startYear + 2 && currentMonth >= startMonth) || (currentYear == startYear + 3 && currentMonth < startMonth)){
                newPrice = BigDecimalUtils.getBigAndBigMul(propertyPrice,new BigDecimal(0.4));
            } else if ((currentYear == startYear + 3 && currentMonth >= startMonth) || (currentYear == startYear + 4 && currentMonth < startMonth)){
                newPrice = BigDecimalUtils.getBigAndBigMul(propertyPrice,new BigDecimal(0.2));
            }
            return BigDecimalUtils.getBigAndBigMul(
                    newPrice,
                    jmArea
            );
        }
    }


    /**
     * 删除发放人对应的减免记录
     * @param housePersonForPropertyId
     */
    @Transactional
    public synchronized void deleteByHousePersonForPropertyId(Integer housePersonForPropertyId) {
        String sql = "delete from reduce_records where house_person_for_property_id =:housePersonForPropertyId";
        this.entityManager.createNativeQuery(sql).setParameter("housePersonForPropertyId", housePersonForPropertyId).executeUpdate();
    }

    /**
     * 删除发放人面积为0的数据
     * @param housePersonForPropertyId
     */
    @Transactional
    public synchronized void deleteByZero(Integer housePersonForPropertyId) {
        String sql = "delete from reduce_records where house_person_for_property_id =:housePersonForPropertyId and money <= 0 ";
        this.entityManager.createNativeQuery(sql).setParameter("housePersonForPropertyId", housePersonForPropertyId).executeUpdate();
    }

    /**
     * 2024年物业减免封装
     * @param yearNow[需查询减免年份]
     * @return
     */
    public Map<String, Map> getJmMap(Integer yearNow) {
        StringBuffer sql = new StringBuffer("SELECT h.az_project_id as 'azProjectId',r.year,r.month,SUM(IFNULL(r.money,0)) AS 'monthMoney',SUM(IFNULL(hpfp.free_area,0)) AS 'jmArea' ");
        sql.append("FROM reduce_records r LEFT JOIN house_person_for_property hpfp ON r.house_person_for_property_id = hpfp.id LEFT JOIN house h ON hpfp.house_id = h.id ");
        sql.append("WHERE r.year =:yearNow ");
        sql.append("GROUP BY r.year,r.month ");
        Query query = this.entityManager.createNativeQuery(sql.toString());
        List<Map> mapList = query.unwrap(org.hibernate.SQLQuery.class).setParameter("yearNow",yearNow).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
        Map<String, Map> resultMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(mapList)) {
            for (Map map : mapList) {
                String azProjectId = map.get("azProjectId").toString();
                String year = map.get("year").toString();
                String month = map.get("month").toString();
                String key = azProjectId + "_" + year + "_" + month;
                resultMap.put(key,map);
            }
        }
        return resultMap;
    }

    /**
     * 物业费减免明细查看
     * @param azProjectId 安置项目Id
     * @param yearNow 减免年份
     * @param month 减免月份
     * @return
     */
    public List<Map> getJmMxList(String azProjectId,String yearNow,String month) {
        StringBuffer sql = new StringBuffer("SELECT h.id as 'houseId',ap.property_price as 'propertyPrice',zp.project_name AS 'zsProjectName',c.property_type AS 'propertyType',ap.project_name AS 'azProjectName', ");
        sql.append("h.build_num AS 'buildNum',h.house_num AS 'houseNum',h.house_hold AS 'houseHold',IFNULL(h.property_area,0) + IFNULL(h.pool_area,0) AS 'buildArea'  ");
        sql.append("FROM house h,contract c,az_project ap,zs_project zp  ");
        sql.append("WHERE h.contract_id = c.id AND h.az_project_id = ap.id AND c.zs_project_id = zp.id ");
        sql.append("AND ap.id =:azProjectId ");
        sql.append("AND h.id IN ");
        sql.append("( ");
        sql.append("SELECT DISTINCT hpfp.house_id  ");
        sql.append("FROM reduce_records r LEFT JOIN house_person_for_property hpfp ON r.house_person_for_property_id = hpfp.id  ");
        sql.append("WHERE r.year =:yearNow ");
        sql.append("AND r.month =:month ");
        sql.append(") ");

        Query query = this.entityManager.createNativeQuery(sql.toString());
        List<Map> mapList = query.unwrap(org.hibernate.SQLQuery.class)
                .setParameter("azProjectId",azProjectId)
                .setParameter("yearNow",yearNow)
                .setParameter("month",month)
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
        return mapList;
    }

    /**
     * 物业明细查看
     * @param azProjectId
     * @param yearNow
     * @param month
     * @return
     */
    public Map<String,List<Map>> getPeopleJm(String azProjectId,String yearNow,String month) {
        Map<String,List<Map>> resultMap = new HashMap<>();
        StringBuffer sql = new StringBuffer("SELECT hpfp.house_id AS 'houseId',r.year AS 'year',r.month AS 'month',r.money AS 'money' ");
        sql.append(",hpfp.name AS 'name',hpfp.id_card AS 'idCard',DATE_FORMAT(hpfp.start_date,'%Y-%m-%d') AS 'startDate' ");
        sql.append(",DATE_FORMAT(hpfp.stop_date,'%Y-%m-%d') AS 'stopDate',hpfp.free_area AS 'freeArea',hpfp.memo AS 'memo' ");
        sql.append("FROM reduce_records r LEFT JOIN house_person_for_property hpfp ON r.house_person_for_property_id = hpfp.id LEFT JOIN house h ON hpfp.house_id = h.id ");
        sql.append("WHERE ");
        sql.append("r.year =:yearNow ");
        sql.append("AND h.az_project_id =:azProjectId ");
        sql.append("AND r.month =:month ");
        Query query = this.entityManager.createNativeQuery(sql.toString());
        List<Map> mapList = query.unwrap(org.hibernate.SQLQuery.class)
                .setParameter("azProjectId",Integer.valueOf(azProjectId))
                .setParameter("yearNow",Integer.valueOf(yearNow))
                .setParameter("month",Integer.valueOf(month))
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
        if (CollectionUtils.isNotEmpty(mapList)) {
            for (Map map : mapList) {
                String key = map.get("houseId").toString();
                if (resultMap != null && resultMap.get(key) == null){
                    List<Map> itemListMap = new LinkedList<>();
                    itemListMap.add(map);
                    resultMap.put(key,itemListMap);
                } else {//此处key 键值对未做判空处理 发送短信是要做判空处理
                    List<Map> itemListMap = resultMap.get(key);
                    itemListMap.add(map);
                    resultMap.put(key,itemListMap);
                }
            }
        }
        return  resultMap;
    }
}
